//package com.zhz.mall.common.util.feign;
//
//import feign.Request;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.annotation.Around;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.annotation.Pointcut;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.springframework.stereotype.Component;
//
//import java.util.concurrent.TimeUnit;
//
///**
// * FeignOptionsInterceptor
// * <p>
// * 通过 Options 注解控制方法级别的超时时间
// *
// * @author zhangjiawei@sanyygp.com
// * @version 1.0
// * @date 2020/12/08 15:12
// * @see Request.Options
// * @see feign.Client
// * @see org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient
// */
//@Aspect
//@Component
//public class FeignOptionsInterceptor {
//
//    static final ThreadLocal<Request.Options> OPTIONS_HOLDER = new ThreadLocal<>();
//
//
//    @Pointcut("@annotation(Options)")
//    public void optionsPointcut() {}
//
//
//    @Pointcut("execution(* feign.Client.execute(..))")
//    public void feignClientPointcut() {}
//
//
//    @Around("optionsPointcut() && @annotation(options)")
//    public Object aroundFeignApi(ProceedingJoinPoint joinPoint, Options options) throws Throwable {
//        // 如果入参中含有 Options 选项, 则不进行对 Options 注解的处理
//        if (OPTIONS_HOLDER.get() == null && !isOptionsParamExists(joinPoint.getArgs())) {
//            OPTIONS_HOLDER.set(toOptions(options));
//        }
//
//        try {
//            return joinPoint.proceed();
//        } finally {
//            removeOptions();
//        }
//    }
//
//
//    @Around("feignClientPointcut()")
//    public Object aroundFeignClientExecute(ProceedingJoinPoint joinPoint) throws Throwable {
//        Request.Options options = OPTIONS_HOLDER.get();
//        if (options == null) {
//            return joinPoint.proceed();
//        }
//
//        try {
//            Object[] args = joinPoint.getArgs();
//            ((MethodSignature) joinPoint.getSignature()).getParameterTypes()[args.length - 1].asSubclass(Request.Options.class);
//
//            // 替换掉默认的超时参数
//            args[args.length - 1] = options;
//            return joinPoint.proceed(args);
//        } finally {
//            removeOptions();
//        }
//    }
//
//
//    /**
//     * 判断 feign api 的参数中是否存在 Options 参数
//     */
//    private boolean isOptionsParamExists(Object[] args) {
//        if (args == null) {
//            return false;
//        }
//        for (Object arg : args) {
//            if (arg instanceof Request.Options) {
//                return true;
//            }
//        }
//        return false;
//    }
//
//
//    private Request.Options toOptions(Options options) {
//        return new Request.Options(options.connectTimeout(), TimeUnit.SECONDS,
//                options.readTimeout(), TimeUnit.SECONDS, options.followRedirects());
//    }
//
//
//    private void removeOptions() {
//        OPTIONS_HOLDER.remove();
//    }
//
//
//}
